It seems that the key thing is that you're basically keeping the parser from interpreting the function as a function declaration, and instead it's being interpreted as an anonymous function expression.
Using the parens to group the expression or using the ! to negate the return are both just techniques of changing the parsing. It's then immediately invoked by the following parens. Any and all of these forms are having the same net effect in that regard, assuming no explicit return value:
(function(){ /* ... */ })(); // Arguably most common form, => undefined
(function(){ /* ... */ }()); // Crockford-approved version, => undefined
!function(){ /* ... */ }(); // Negates the return, so => true
+function(){ /* ... */ }(); // Attempts numeric conversion of undefined, => NaN
~function(){ /* ... */ }(); // Bitwise NOT, => -1
If you're not capturing the returned value, there's no significant difference. One could argue that the ~ might be a faster op since it's just flipping bits, or maybe ! is a faster op since it's a true/false check and returning the negation.
At the end of the day though, the way most people are using this pattern is that they're trying to break off a new level of scope to keep things clean. Any and all work. The latter forms are popular because while they do introduce an additional (typically unnecessary) operation, saving every extra byte helps.
Ben Alman has a fantastic writeup on the topic: http://benalman.com/news/2010/11/immediately-invoked-function-expression/