By using table.insert the table is indexed by continuous integers (1,2,3, etc).
This makes possible to iterate over the table with ipairs instead of pairs, so iterating over the table is more efficient.
It is also possible to automatically calculate the table length with #tbl.
Integers also take a little bit less memory - but not much more.
So table.insert is better with tables that are going to be iterated over a lot, and where the keys don't "matter" (so you can use numbers). Typically these are "lists of elements": lists of enemies, items, tiles on a map... that sort of thing. On these lists you normally don't know exactly how many elements you will have.
On the other hand, for us humans it is much easier to understand if you say tbl.body instead of tbl[2], for example.
On the efficiency department, table.insert is a function; It's slower than doing tbl.key = value.
So tbl.key = value is better when the table isn't going to be parsed over with a loop, or the keys have a "meaning" for the programmer. These are typically "object-like"; the element returned by tbl.key is "a property" of tbl, not an element on a list. On this kind of tables you know exactly how many keys you will have, and each has one name.