The value returned in line (1) is always the current value of i, not the value it had when the function was created. After the loop is finished, i has the value 5, which is why all functions in the array return that value.
Gdy wywołujesz funkcję poza pętlą, to closure umożliwia Ci dostęp do zmiennej i (bo pamięta środowisko, w którym została utworzona zmienna), ale jej wartość jako ostatnia została ustawiona na 5 - bo na tym pętla się zakończyła.
IIFE powoduje, że funkcja wywołuje się w momencie jej tworzenia. W drugim przykładzie masz
var i2 = i; // copy current i
Co powoduje, że wartość iteratora jest kopiowana (bo wartości prymitywne w JS, w przeciwieństwie do obiektów, są kopiowane) do tymczasowej zmiennej w momencie, gdy ma ona konkretną wartość- a dzięki IIFE, można potem ją wywołać z jej ówczesną wartością (taką, jaką wtedy miało i).
Tu masz więcej przykładów z IIFE: http://benalman.com/news/2010/11/immediately-invoked-function-expression/