There are two responses here. The first is that in any language which has any sort of threading model at all, sequential code in multiple threads obviates the need for callbacks. If you block, fine; it's just a single thread, it's not obstructing the handling of other threads. Why don't Python and JavaScript have multithreading? Well, because programming with unrestricted concurrency and mutable state is really difficult. But there are ways to solve this problem, Haskell's purity being one among several.
The second is that do-notation is distinct from the IO monad. Even if Haskell didn't have green threads in the runtime, I could still write an async/callback library that looked just as natural as sequential code. Why? It has nothing to do with the IO monad: it has to do with the fact that "do x <- e; m" desugars to, in JavaScript notation, bind(e, function(x) { m }); it's been "callbackified automatically".