There are some interesting examples of custom awaiters in Stephen Toub's Await Anything blog post. I specifically like await task.WithCulture() pattern which I think can be useful in real life. However, I can't think of anything else that possibly cannot be done with TaskCompletionSource.
One interesting field where it might be useful for is switching of execution contexts, like with ControlAwaiter from Stephen's blog or ContextSwitcher from this question. Yet this is not considered a good practice, AFAIU.
It'd be interesting to see some other practical and useful examples of custom awaiters, which still would not harm code readability and maintainability.