It's the golden unsolved, perhaps unsolvable problem in crypto. Trusting trust and such. There's always a key, somewhere, that has to be shared.
One way to hack the system is if you have actual knowledge of the person you are talking to, and you assume some limited amount of tampering which can be done in real-time. For example, if I know the sound of your voice, and we want to agree on a key with no MITM, we can setup an audio channel and speak some code words to each other. Baring an adversary which can in real-time intercept and synthesize my voice convincingly speaking a different code, this is pretty secure. [1]
[ZRTP] allows the detection of man-in-the-middle (MiTM) attacks by displaying a short
authentication string (SAS) for the users to read and verbally compare over the phone.
Another imperfect defense is spreading over time the data that an attacker would have to intercept and modify in order to MITM. That's what Chrome is doing with their pin lists. Now an adversary would have to alter the pinning when Chrome is downloaded. Of course in this very thread we're talking about technology which can do exactly that. E.g. technology which has any hope of preventing data exfiltration, would have an easy time altering Chrome's pin-list. Of course the Chrome binaries are signed, so there's another layer to defeat, etc. etc.
So the end result is there are a lot of good technologies to prevent MITM. If you can keep the attacker out once, you can generally be confident your future conversations will be secure as well, since good protocols don't start from scratch each time, but rather "ratchet" new keys from the old as you go. [2]
One of the big trade-offs is false positives and privacy. For example, it might be nice if my browser remembered the public key of a site I visit, like HN, and let me know if it changed. Two issues are a naive implementation would also serve as a great tracker for every site I've visited, and how do I know if when I get a warning, it's a real attack and not just an expiring certificate rotating out? Now we would need a way for sites to indicate, by signing with their old key, that indeed they are switching to a new key, and complexity explodes from there.
[1] - http://blog.cryptographyengineering.com/2012/11/lets-talk-ab...
[2] - https://whispersystems.org/blog/advanced-ratcheting/