It all depends on what you want to do. I do not think it is usuful to use dlXXX with libC, but may be cases where that may be the way forward. There is no magic solution for all cases. You need to think about what you want to achieve and find the better solution.
For example, using uLibC statically will make your program bigger because all the code you use from libc.so is now included in your binary. On the other hand, your program will work on any system, despite of the libC version installed on it. As I said, it depends on what you want. If you are targetting routers… many of those runs busybox using uLibC… no libc.so in the filesystem …so you will have to transfer the library together with your program to make it work. So, you are not saving any space in the size of your program… actually the other way around.
The easy way to make your code polymorphic is using a crypter. Over all, you want your crypter stub to be small as that is the part that doesn’t change and that is why many times it is implemented in asm (among other reasons), but you can implement the stub in C if you want. Take a look to this series on crypters from some time ago. Still valid tho, as far as I reckon . The stub is coded in asm on those posts, but they describe what you have to do, so you just can implement it using C: